package net.cl.util.ui;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;

import net.cl.util.ui.SlideshowPanel.SlideOrientation;


/**
 * Special LayoutManager exclusively designed for the SlideshowPanel class.
 *
 * Puts the view panel at the correct position.
 *
 * @author David
 */
class SlideshowPanelLayout implements LayoutManager
{
	private int						mMinWidth			= 0;
	private int						mMinHeight			= 0;
	private int						mPreferredWidth		= 0;
	private int						mPreferredHeight	= 0;
	private boolean					mSizeUnknown		= true;

	private Component				mActiveComponent	= null;
	private SlideshowContentPane	mContentPanel		= null;

	private SlideOrientation		mOrientation;

	public SlideshowPanelLayout(SlideOrientation pOrientation)
	{
		this.mOrientation = pOrientation;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void addLayoutComponent(String arg0, Component arg1)
	{
		// - Not needed -
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void removeLayoutComponent(Component arg0)
	{
		// - Not needed -
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Dimension minimumLayoutSize(Container pParent)
	{
		updateSize(pParent);

		Insets insets = pParent.getInsets();
		int width = this.mMinWidth + insets.left + insets.right;
		int height = this.mMinHeight+ insets.top + insets.bottom;

		return new Dimension(width, height);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Dimension preferredLayoutSize(Container pParent)
	{
		updateSize(pParent);

		Insets insets = pParent.getInsets();
		int width = this.mPreferredWidth + insets.left + insets.right;
		int height = this.mPreferredHeight + insets.top + insets.bottom;

		return new Dimension(width, height);
	}

	@Override
	public void layoutContainer(Container pParent)
	{
		if(this.mSizeUnknown)
		{
			this.updateSize(pParent);
		}

		Insets insets = pParent.getInsets();

		if(this.mActiveComponent == null)
		{
			if(this.mContentPanel.getComponentCount() > 0)
			{
				this.mActiveComponent = this.mContentPanel.getComponents()[0];
			}
			else
			{
				// No components available to lay out...
				return;
			}
		}

		this.mContentPanel.setMaxWidthPerComponent(pParent.getWidth() - insets.left - insets.right);
		this.mContentPanel.setMaxHeightPerComponent(pParent.getHeight() - insets.top - insets.bottom);

		double targetVal = this.mOrientation.getTargetValue(pParent, mActiveComponent, mContentPanel);
		if(this.mOrientation == SlideOrientation.VERTICAL)
		{
			this.mContentPanel.setLocation(insets.left, insets.top - this.mActiveComponent.getY());
			this.mContentPanel.setSize(this.mContentPanel.getMaxWidthPerComponent(),
					this.mContentPanel.getRequiredHeight());
		}
		else
		{
			this.mContentPanel.setLocation((int) targetVal, insets.top);
			this.mContentPanel.setSize(this.mContentPanel.getRequiredWidth(),
					this.mContentPanel.getMaxHeightPerComponent());
		}
	}

	/**
	 * Updates the preferred and minimum size of the layout.
	 *
	 * @param pParent The parent component. Must be of type SlidingPanel.
	 * @throws IllegalArgumentException if pCont is not of type SlidingPanel
	 */
	private void updateSize(Container pParent)
	{
		// Reset preferred/minimum width and height.
		this.mPreferredWidth = 0;
		this.mPreferredHeight = 0;
		this.mMinWidth = 0;
		this.mMinHeight = 0;

		// Compute the sizes as the maximum of all the component's values
		for(Component c : pParent.getComponents())
		{
			this.mPreferredWidth = Math.max(this.mPreferredWidth, c.getPreferredSize().width);
			this.mPreferredHeight = Math.max(this.mPreferredHeight, c.getPreferredSize().height);
			this.mMinWidth = Math.max(this.mMinWidth, c.getMinimumSize().width);
			this.mMinHeight = Math.max(this.mMinHeight, c.getMinimumSize().height);
		}

		this.mSizeUnknown = false;
	}

	@Override
	public String toString()
	{
		return getClass().getSimpleName();
	}

	void setActiveComponent(Component pComp)
	{
		this.mActiveComponent = pComp;
	}

	void setContentPanel(SlideshowContentPane pPanel)
	{
		this.mContentPanel = pPanel;
	}
}